package com.example.data.factory.service.service.Impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.data.factory.common.Dto.*;
import com.example.data.factory.common.common.StringConstant;
import com.example.data.factory.common.result.PageVO;
import com.example.data.factory.common.result.R;
import com.example.data.factory.common.util.CommonUtil;
import com.example.data.factory.common.util.ParamParser;
import com.example.data.factory.entity.entity.Classify;
import com.example.data.factory.entity.entity.Dict;
import com.example.data.factory.entity.entity.Interface;
import com.example.data.factory.entity.entity.InterfaceParam;
import com.example.data.factory.mapper.mapper.ClassifyMapper;
import com.example.data.factory.mapper.mapper.DictMapper;
import com.example.data.factory.mapper.mapper.InterfaceMapper;
import com.example.data.factory.service.service.DictService;
import com.example.data.factory.service.service.InterfaceParamService;
import com.example.data.factory.service.service.InterfaceService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author lhy
 * @since 2025-03-03
 */

@Service
public class InterfaceServiceImpl extends ServiceImpl<InterfaceMapper, Interface> implements InterfaceService {
    private static final Logger logger = LoggerFactory.getLogger ( InterfaceServiceImpl.class );
    @Resource
    private ClassifyMapper classifyMapper;
    @Resource
    private InterfaceParamService interfaceParamService;
    @Resource
    private InterfaceMapper interfaceMapper;
    @Resource
    private InterfaceTestService interfaceTestService;
    @Resource
    private CommonUtil commonUtil;

    @Resource
    private DictMapper dictMapper;
    @Resource
    private DictService dictService;

    @Override
    public R<Interface> search(SearchInterfaceDTO searchInterfaceDTO) {
        Page<Interface> page = new Page<> ( searchInterfaceDTO.getPageNumber (), searchInterfaceDTO.getPageSize () );
        LambdaQueryWrapper<Interface> wrapper = new LambdaQueryWrapper<Interface> ()
                .like ( StringUtils.isNotBlank ( searchInterfaceDTO.getInterfaceName () ), Interface::getInterfaceName, searchInterfaceDTO.getInterfaceName () )
                .eq ( StringUtils.isNotBlank ( searchInterfaceDTO.getSource () ), Interface::getSource, searchInterfaceDTO.getSource () )
                .eq ( searchInterfaceDTO.getStatus () != null, Interface::getStatus, searchInterfaceDTO.getStatus () )
                .eq ( Interface::getDeleted, 0 );
        Page<Interface> page1 = this.page ( page, wrapper );
        PageVO<Interface> pageVO = new PageVO<> ();
        BeanUtil.copyProperties ( page1, pageVO );
        return R.Success ( pageVO );
    }

    public String buildCategoryPath(Long id) {
        StringBuilder fullPath = new StringBuilder ();
        Classify currentCategory = classifyMapper.selectById ( id );

        // 递归向上查找直到根节点
        while (currentCategory != null) {
            if (fullPath.length () > 0) {
                fullPath.insert ( 0, "/" );
            }
            fullPath.insert ( 0, currentCategory.getName () );
            if (currentCategory.getParentId () != null && !currentCategory.getParentId ().equals ( 0L )) {
                currentCategory = classifyMapper.selectById ( currentCategory.getParentId () );
            } else {
                break;
            }
        }
        return fullPath.toString ();
    }

    @Override
    public R<Interface> insert(InsertInterfaceDto insertInterfaceDto, HttpServletRequest request) {
        String categoryName = insertInterfaceDto.getCategoryName ();
        if (categoryName == null || categoryName.trim ().isEmpty ()) {
            return R.Failed ( "无效的分类名称" );
        }

        try {
            Classify classify = classifyMapper.selectByname ( categoryName );
            if (classify == null) {
                return R.Failed ( "没有找到分类" );
            }

            // 获取用户选择的完整路径
            String categoryPath = buildCategoryPath ( Long.valueOf ( classify.getId () ) );

            Interface anInterface = new Interface ();
            BeanUtil.copyProperties ( insertInterfaceDto, anInterface );
            List<Interface> list = this.list ();
            String username = commonUtil.extractUsernameFromRequest ( request );
            // 设置分类ID及完整路径
            anInterface.setClassifyId ( Long.valueOf ( classify.getId () ) );
            anInterface.setCategoryName ( categoryPath );
            anInterface.setCreateBy ( username );
            anInterface.setCreateTime ( LocalDateTime.now () );
            anInterface.setUpdateTime ( LocalDateTime.now () );
            if (list.stream ().anyMatch ( data -> data.getInterfaceName ().equals ( insertInterfaceDto.getInterfaceName () ) )
                    || list.stream ().anyMatch ( data -> data.getPath ().equals ( insertInterfaceDto.getPath () ) )) {
                return R.Failed ( StringConstant.ERRO );
            }
            boolean saveResult = this.save ( anInterface );
            if (saveResult) {
                return R.Success ( StringConstant.INSERTSUCCESS );
            } else {
                return R.Failed ( StringConstant.INSERTFAILD );
            }
        } catch (Exception e) {
            log.error ( "插入接口信息失败", e );
            return R.Failed ( "系统内部错误" );
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public R<Interface> insets(InsertInterfaceAndInterfaceParamDto dto, HttpServletRequest request) {
        // 1. 参数基础校验
        if (dto == null || request == null) {
            return R.Failed ( "请求参数不能为空" );
        }

        String categoryName = dto.getCategoryName ();
        if (StringUtils.isBlank ( categoryName )) {
            return R.Failed ( "分类名称不能为空" );
        }

        try {
            // 2. 验证分类是否存在
            Classify classify = classifyMapper.selectByname ( categoryName.trim () );
            if (classify == null) {
                return R.Failed ( "分类不存在: " + categoryName );
            }

            // 3. 检查接口名称唯一性（优化查询方式）
            boolean exists = this.lambdaQuery ()
                    .eq ( Interface::getInterfaceName, dto.getInterfaceName ().trim () )
                    .exists ();
            if (exists) {
                return R.Failed ( "不存在" );
            }

            // 4. 构建接口实体
            String username = commonUtil.extractUsernameFromRequest ( request );
            Interface newInterface = new Interface ();
            BeanUtils.copyProperties ( dto, newInterface );

            newInterface.setClassifyId ( Long.valueOf ( classify.getId () ) );
            newInterface.setCategoryName ( buildCategoryPath ( Long.valueOf ( classify.getId () ) ) );
            newInterface.setCreateBy ( username );
            newInterface.setCreateTime ( LocalDateTime.now () );
            newInterface.setUpdateTime ( LocalDateTime.now () );

            // 5. 保存接口主体信息
            if (!this.save ( newInterface )) {
                log.error ( "接口保存失败: {}" );
                return R.Failed ( "接口信息保存失败" );
            }

            // 6. 处理参数中的码表信息
            processAllParameters ( newInterface.getId (), dto, request );

            return R.Success ( StringConstant.INSERTSUCCESS, newInterface );
        } catch (Exception e) {

            return R.Failed ();
        }
    }

    /**
     * 处理所有参数（输入参数、请求体、输出参数）
     */
    private void processAllParameters(Integer interfaceId,
                                      InsertInterfaceAndInterfaceParamDto dto,
                                      HttpServletRequest request) throws Exception {
        processSingleParameter ( interfaceId, dto.getInputParam (), (byte) 1, request );
        processSingleParameter ( interfaceId, dto.getInputParamBody (), (byte) 2, request );
        processSingleParameter ( interfaceId, dto.getOutputParam (), (byte) 3, request );
    }

    /**
     * 处理单个参数
     */
    private void processSingleParameter(Integer interfaceId,
                                        String paramJson,
                                        byte paramType,
                                        HttpServletRequest request) throws Exception {
        if (StringUtils.isBlank ( paramJson )) return;

        try {
            JsonNode root = new ObjectMapper ().readTree ( paramJson );
            JsonNode dictNameNode = root.path ( "dictName" );
            JsonNode dictValueNode = root.path ( "dictValue" );

            // 仅当包含 dictName 和 dictValue 时才处理码表
            if (!dictNameNode.isMissingNode () && !dictValueNode.isMissingNode ()) {
                handleDictCreation (
                        dictNameNode.asText (),
                        root.path ( "dictDescription" ).asText ( "" ), // 默认空字符串
                        dictValueNode,
                        request
                );
            }

            saveInterfaceParam ( interfaceId, paramJson, paramType );
        } catch (JsonProcessingException e) {
            log.error ( "参数JSON解析失败: {}" );
            throw new Exception ( "参数格式错误" );
        } catch (Exception e) {
            log.error ( "参数处理异常", e );
            throw new Exception ( "参数处理失败" );
        }
    }

    /**
     * 处理码表创建逻辑
     */
    private void handleDictCreation(String dictName,
                                    String dictDescription,
                                    JsonNode dictValueNode,
                                    HttpServletRequest request) throws Exception {
        try {
            // 1. 检查码表是否存在（仅按名称判断）
            Dict existingDict = dictMapper.selectByDictName ( dictName );
            if (existingDict != null) {
                return;
            }

            // 2. 构建码表数据
            InsertDictDto insertDto = new InsertDictDto ();
            insertDto.setDictName ( dictName );
            insertDto.setDescription ( dictDescription );

            List<InsertDictDataDto> dataList = new ArrayList<> ();
            InsertDictDataDto dataDto = new InsertDictDataDto ();
            dataDto.setDictValue ( dictValueNode.path ( "value" ).asText () );
            dataDto.setDictLabel ( dictValueNode.path ( "valueName" ).asText () );
            dataDto.setDescription ( dictValueNode.path ( "valueDescription" ).asText () );
            dataList.add ( dataDto );
            insertDto.setDictDataDtos ( dataList );

            // 3. 调用服务插入码表
            R<Dict> result = dictService.insert ( insertDto, request );
            if (result == null || result.failed ()) {
                String errorMsg = result != null ? result.getMsg () : "无返回结果";
                log.error ( "码表插入失败 | 名称:{} | 原因:{}" );
                throw new Exception ( "码表创建失败: " + errorMsg );
            }
        } catch (Exception e) {
            log.error ( "码表处理异常: {}" );
            throw new Exception ( "码表处理失败" );
        }
    }

    @Override
    public R<Interface> updates(UpdateInterfaceAndInterfaceParamDto updateInterfaceAndInterfaceParamDto) {
        // 获取原始接口信息
        Interface originalInterface = this.getById ( updateInterfaceAndInterfaceParamDto.getId () );
        if (originalInterface == null) {
            return R.Failed ( "找不到该条信息" );
        }
        if (originalInterface.getStatus () == 1) {
            return R.Failed ( StringConstant.UPDATEERRO );
        }

        // 检查接口名称是否重复（排除当前正在更新的记录）
        boolean exists = this.list ( new QueryWrapper<Interface> ()
                        .ne ( "id", updateInterfaceAndInterfaceParamDto.getId () )
                        .eq ( "interface_name", updateInterfaceAndInterfaceParamDto.getInterfaceName () ) )
                .stream ().anyMatch ( data -> data.getInterfaceName ().equals ( updateInterfaceAndInterfaceParamDto.getInterfaceName () ) );
        if (exists) {
            return R.Failed ( "接口名称重复，无法修改" );
        }

        // 更新接口信息
        boolean updateResult = this.update ( new LambdaUpdateWrapper<Interface> ()
                .set ( Interface::getInterfaceName, updateInterfaceAndInterfaceParamDto.getInterfaceName () )
                .set ( Interface::getSource, updateInterfaceAndInterfaceParamDto.getSource () )
                .set ( Interface::getDescription, updateInterfaceAndInterfaceParamDto.getDescription () )
                .set ( Interface::getProtocol, updateInterfaceAndInterfaceParamDto.getProtocol () )
                .set ( Interface::getIpAndProt, updateInterfaceAndInterfaceParamDto.getIpAndProt () )
                .set ( Interface::getPath, updateInterfaceAndInterfaceParamDto.getPath () )
                .set ( Interface::getRequest, updateInterfaceAndInterfaceParamDto.getRequest () )
                .set ( Interface::getInputParam, updateInterfaceAndInterfaceParamDto.getInputParam () )
                .set ( Interface::getInputParamBody, updateInterfaceAndInterfaceParamDto.getInputParamBody () )
                .set ( Interface::getOutputParam, updateInterfaceAndInterfaceParamDto.getOutputParam () )
                .set ( Interface::getTimeout, updateInterfaceAndInterfaceParamDto.getTimeout () )
                .set ( Interface::getCategoryName, updateInterfaceAndInterfaceParamDto.getCategoryName () )
                .eq ( Interface::getId, updateInterfaceAndInterfaceParamDto.getId () ) );

        if (!updateResult) {
            return R.Failed ( "更新失败" );
        }

        String categoryName = updateInterfaceAndInterfaceParamDto.getCategoryName ();
        if (categoryName == null || categoryName.trim ().isEmpty ()) {
            return R.Failed ( "无效的分类名称" );
        }
        try {
            Classify classify = classifyMapper.selectByname ( categoryName );
            if (classify == null) {
                return R.Failed ( "没有找到分类" );
            }

            // 构建分类路径
            String categoryPath = buildCategoryPath ( Long.valueOf ( classify.getId () ) );

            // 更新接口表中的分类ID和分类名称
            Interface updatedInterface = new Interface ();
            updatedInterface.setId ( updateInterfaceAndInterfaceParamDto.getId () );
            updatedInterface.setClassifyId ( Long.valueOf ( classify.getId () ) );
            updatedInterface.setCategoryName ( categoryPath );
            updatedInterface.setUpdateTime ( LocalDateTime.now () );

            this.updateById ( updatedInterface );

            // 保存接口参数
            Integer id = updateInterfaceAndInterfaceParamDto.getId ();
            saveInterfaceParam ( id, updateInterfaceAndInterfaceParamDto.getInputParam (), (byte) 1 );
            saveInterfaceParam ( id, updateInterfaceAndInterfaceParamDto.getInputParamBody (), (byte) 2 );
            saveInterfaceParam ( id, updateInterfaceAndInterfaceParamDto.getOutputParam (), (byte) 3 );

            return R.Success ( StringConstant.UPDATESUCCESS );
        } catch (Exception e) {
            log.error ( "更新接口信息失败", e );
            throw new RuntimeException ( e );
        }
    }

    @Override
    public R<Interface> updatestatus(UpdateInterfaceStatusDto updateInterfaceStatusDto) {
        Interface byId = this.getById ( updateInterfaceStatusDto.getId () );
        if (byId == null) {
            return R.Failed ( "找不到该条数据" );
        }
        if (byId.getDeleted () == 1) {
            return R.Failed ( "数据已删除，无法修改" );
        }
        boolean update = this.update ( new LambdaUpdateWrapper<Interface> ().set ( Interface::getStatus, updateInterfaceStatusDto.getStatus () )
                .eq ( Interface::getId, updateInterfaceStatusDto.getId () ) );
        if (update) {
            Interface anInterface = new Interface ();
            anInterface.setUpdateTime ( LocalDateTime.now () );
            return R.Success ( StringConstant.UPDATESUCCESS );
        }
        return R.Failed ( StringConstant.UPDATEFAILED );
    }

    @Override
    public R<Interface> updatestatsbatch(List<UpdateInterfaceStatusDto> updateInterfaceStatusDtos) {
        if (updateInterfaceStatusDtos == null || updateInterfaceStatusDtos.isEmpty ()) {
            return R.Failed ( "数据不存在" );
        }
        boolean allsuccess = true;
        for (UpdateInterfaceStatusDto dto : updateInterfaceStatusDtos) {
            Interface one = this.getOne ( new LambdaQueryWrapper<Interface> ().eq ( Interface::getId, dto.getId () )
                    .eq ( Interface::getDeleted, 0 ) );
            if (one == null) {
                allsuccess = false;
                continue;
            }
            Interface anInterface = new Interface ();
            anInterface.setUpdateTime ( LocalDateTime.now () );
            boolean update = this.update ( new LambdaUpdateWrapper<Interface> ().set ( Interface::getStatus, dto.getStatus () )
                    .eq ( Interface::getId, dto.getId () ) );
            if (!update) {
                allsuccess = false;
            }
        }
        if (allsuccess) {
            return R.Success ( StringConstant.UPDATESUCCESS );
        } else {
            return R.Failed ( "部分更新失败，可能是由于某些字典项已被删除或更新条件不匹配" );
        }
    }

    @Override
    public R<Interface> delete(DeleteInterfaceDto deleteInterfaceDto) {
        Interface one = this.getOne ( new LambdaQueryWrapper<Interface> ().eq ( Interface::getId, deleteInterfaceDto.getId () ) );
        if (one == null) {
            return R.Failed ( "找不到该条信息" );
        }
        if (!(one.getStatus () == 0)) {
            return R.Failed ( "只能在未发布的状态下进行删除" );
        }
        one.setDeleted ( (byte) 1 );
        one.setUpdateTime ( LocalDateTime.now () );
        boolean save = this.updateById ( one );
        if (save) {
            return R.Success ( StringConstant.UPDATESUCCESS );
        }
        return R.Failed ( StringConstant.UPDATEFAILED );
    }

    @Override
    public R<Interface> searchdetail(DeleteInterfaceDto deleteInterfaceDto) {
        Interface one = this.getOne ( new LambdaQueryWrapper<Interface> ()
                .eq ( Interface::getId, deleteInterfaceDto.getId () ) );
        if (one == null) {
            return R.Failed ( "该编号下数据为空" );
        }
        return R.Success ( one );
    }

    @Override
    public R<Map<String, String>> classifyBatch(ClassifyBatch request) {
        // 解析请求参数
        List<String> interfaceNames = request.getInterfaceName ();
        String categoryName = request.getCategoryName ();

        // 检查输入数据是否有效
        if (interfaceNames == null || interfaceNames.isEmpty () || categoryName == null || categoryName.trim ().isEmpty ()) {
            return R.Failed ( "未输入有效的数据" );
        }

        Map<String, String> results = new HashMap<> (); // 用于记录每个接口的更新结果

        // 查询分类是否存在
        Classify classify = classifyMapper.selectByname ( categoryName );
        if (classify == null) {
            for (String interfaceName : interfaceNames) {
                results.put ( interfaceName, "没有找到分类" );
            }
            return R.Failed ( results.toString () );
        }

        // 构建分类路径
        String categoryPath = buildCategoryPath ( Long.valueOf ( classify.getId () ) );

        for (String interfaceName : interfaceNames) {
            Interface one = this.getOne ( new LambdaQueryWrapper<Interface> ()
                    .eq ( Interface::getInterfaceName, interfaceName ) );
            if (one == null) {
                results.put ( interfaceName, "接口不存在" );
                continue;
            }

            boolean updateResult = this.update (
                    new LambdaUpdateWrapper<Interface> ()
                            .set ( Interface::getCategoryName, categoryPath )
                            .set ( Interface::getClassifyId, classify.getId () )
                            .set ( Interface::getUpdateTime, LocalDateTime.now () )
                            .eq ( Interface::getId, one.getId () ) );

            if (!updateResult) {
                results.put ( interfaceName, "更新失败" );
            } else {
                results.put ( interfaceName, "更新成功" );
            }
        }

        long successCount = results.values ().stream ().filter ( result -> result.equals ( "更新成功" ) ).count ();
        long failedCount = results.size () - successCount;

        if (failedCount > 0) {
            return R.Failed ( results.toString () );
        } else {
            return R.Success ( StringConstant.UPDATESUCCESS );
        }
    }

    @Override
    public Map<String, String> testInterfaces(Integer id) {
        // 初始化ObjectMapper（如果是Spring项目可以通过@Autowired注入）
        ObjectMapper objectMapper = new ObjectMapper ();

        Interface iface = interfaceMapper.selectById ( id );
        if (iface == null) {
            throw new RuntimeException ( "接口信息不存在" );
        }

        try {
            String inputParamsJson = String.valueOf ( iface.getInputParam () );

            // 空值检查
            if (StringUtils.isEmpty ( inputParamsJson ) || "null".equals ( inputParamsJson )) {
                return Collections.emptyMap ();
            }

            // 解析JSON
            List<Map<String, Object>> params = objectMapper.readValue (
                    inputParamsJson,
                    new TypeReference<List<Map<String, Object>>> () {
                    }
            );

            Map<String, String> result = new HashMap<> ();
            for (Map<String, Object> param : params) {
                String paramName = (String) param.get ( "paramName" );
                Object defaultValue = param.get ( "paramDefault" );

                if ("id".equals ( paramName ) && defaultValue != null) {
                    result.put ( "id", defaultValue.toString () );
                } else if ("name".equals ( paramName ) && defaultValue != null) {
                    result.put ( "name", defaultValue.toString () );
                }
            }

            return result;
        } catch (JsonProcessingException e) {
            log.error ( "JSON解析失败 - 内容: {}" );
            throw new RuntimeException ( "参数格式不正确", e );
        } catch (Exception e) {
            log.error ( "参数处理失败 - ID: {}" );
            throw new RuntimeException ( "参数处理失败", e );
        }
    }
    /**
     * 测试接口
     */
    public String testInterfaceById(Integer id, Map<String, String> userParams) {
        Interface iface = interfaceMapper.selectById ( id );
        if (iface == null) {
            throw new RuntimeException ( "接口信息不存在" );
        }

        try {
            // 1. 解析默认参数
            Object inputParam = iface.getInputParam ();
            Map<String, String> defaultParams = new HashMap<> ();

            if (inputParam != null && !"null".equals ( inputParam.toString () )) {
                try {
                    defaultParams = ParamParser.parseInputParams ( inputParam.toString () );
                } catch (Exception e) {
                    logger.warn ( "默认参数解析失败，将使用空参数", e );
                }
            }

            logger.info ( "解析后的默认参数: {}", defaultParams );
            logger.info ( "用户传入参数: {}", userParams );

            // 2. 参数合并（用户参数优先）
            Map<String, String> finalParams = new HashMap<> ( defaultParams );
            if (userParams != null) {
                finalParams.putAll ( userParams );
            }

            logger.info ( "合并后的最终参数: {}", finalParams );

            // 3. 调用测试服务
            return interfaceTestService.testInterface ( iface, finalParams, null );
        } catch (Exception e) {
            logger.error ( "接口测试失败 - 接口ID: {}", id, e );
            throw new RuntimeException ( "接口测试失败: " + e.getMessage (), e );
        }
    }

    private void saveInterfaceParam(Integer interfaceId, Object value, byte paramType) {
        if (value != null) {
            try {
                InterfaceParam interfaceParam = new InterfaceParam ();
                interfaceParam.setInterfaceId ( interfaceId );
                interfaceParam.setValue ( value.toString () ); // 确保这里的toString不会抛出异常
                interfaceParam.setParamType ( paramType );
                interfaceParam.setUpdateTime ( LocalDateTime.now () );
                interfaceParam.setCreateTime ( LocalDateTime.now () );
                interfaceParamService.save(interfaceParam);
            } catch (Exception e) {
                log.error("保存InterfaceParam失败", e);
                throw new RuntimeException("保存InterfaceParam失败", e);
            }
        }
    }
}
